home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 015 / bawk2a.arc / BAWKSYM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1986-07-27  |  8.7 KB  |  365 lines

  1. /*
  2.  * Bawk C actions builtin functions, variable declaration, and
  3.  * stack management routines.
  4.  */
  5. #include <stdio.h>
  6.  
  7. #include "bawk.h"
  8.  
  9. #define MAXARGS 10            /* max # of arguments to a builtin func */
  10. #define F_PRINTF 1
  11. #define F_GETLINE 2
  12. #define F_STRLEN 3
  13. #define F_STRCPY 4
  14. #define F_STRCMP 5
  15. #define F_TOUPPER 6
  16. #define F_TOLOWER 7
  17. #define F_MATCH 8
  18. #define F_NEXTFILE 9
  19.  
  20. isfunction ( s )
  21. char *s;
  22. {     
  23. /*
  24.  * Compare the string "s" to a list of builtin functions
  25.  * and return its (non-zero) token number.
  26.  * Return zero if "s" is not a function.
  27.  */
  28.     if ( !strcmp( s, "printf" ) ) return F_PRINTF;
  29.     if ( !strcmp( s, "getline" ) ) return F_GETLINE;
  30.     if ( !strcmp( s, "strlen" ) ) return F_STRLEN;
  31.     if ( !strcmp( s, "strcpy" ) ) return F_STRCPY;
  32.     if ( !strcmp( s, "strcmp" ) ) return F_STRCMP;
  33.     if ( !strcmp( s, "toupper" ) ) return F_TOUPPER;
  34.     if ( !strcmp( s, "tolower" ) ) return F_TOLOWER;
  35.     if ( !strcmp( s, "match" ) ) return F_MATCH;
  36.     if ( !strcmp( s, "nextfile" ) ) return F_NEXTFILE;
  37.     return 0;
  38.     }
  39.  
  40. iskeyword ( s )
  41. char *s;
  42. {     
  43. /*
  44.  * Compare the string "s" to a list of keywords and return its
  45.  * (non-zero) token number.  Return zero if "s" is not a keyword.
  46.  */
  47.     if ( !strcmp( s, "char" ) ) return T_CHAR;
  48.     if ( !strcmp( s, "int" ) ) return T_INT;
  49.     if ( !strcmp( s, "if" ) ) return T_IF;
  50.     if ( !strcmp( s, "else" ) ) return T_ELSE;
  51.     if ( !strcmp( s, "while" ) ) return T_WHILE;
  52.     if ( !strcmp( s, "break" ) ) return T_BREAK;
  53.  
  54.     if ( !strcmp( s, "NF" ) ) return T_NF;
  55.     if ( !strcmp( s, "NR" ) ) return T_NR;
  56.     if ( !strcmp( s, "FS" ) ) return T_FS;
  57.     if ( !strcmp( s, "RS" ) ) return T_RS;
  58.     if ( !strcmp( s, "FILENAME" ) ) return T_FILENAME;
  59.     if ( !strcmp( s, "BEGIN" ) ) return T_BEGIN;
  60.     if ( !strcmp( s, "END" ) ) return T_END;
  61.     return 0;
  62.     }
  63.  
  64. function ( funcnum ) {     
  65.     int argc, args[ MAXARGS ];
  66.     char lpar;
  67.  
  68.     argc = 0;
  69.     if ( Token==T_LPAREN ) { 
  70.         lpar = 1;
  71.         getoken();
  72.         }
  73.     else lpar = 0;
  74. /*
  75.  * If there are any arguments, evaluate them and copy their values
  76.  * to a local array.
  77.  */
  78.     if ( Token!=T_RPAREN && Token!=T_EOF ) { 
  79.         for ( ;; ) { 
  80.             expression();
  81.             if ( argc<MAXARGS ) args[ argc++ ] = popint();
  82.             else popint();
  83.             if ( Token==T_COMMA ) getoken();
  84.             else break;
  85.             }
  86.         }
  87.     if ( lpar && Token!=T_RPAREN ) error( "missing ')'", ACT_ERROR );
  88.     else if ( Token==T_RPAREN ) getoken();
  89.  
  90.     switch ( funcnum ) { 
  91.        case F_PRINTF:                /* just like the real printf() function */
  92.            pushint( printf( args[0], args[1], args[2], args[3], args[4],
  93.            args[5], args[6], args[7], args[8], args[9] ) );
  94.            break;
  95.        case F_GETLINE:
  96. /*
  97.  * Get the next line of input from the current input file
  98.  * and parse according to the current field seperator.
  99.  * Don't forget to free up the previous line's words first...
  100.  */
  101.            while ( Fieldcount ) free( Fields[ --Fieldcount ] );
  102.            pushint( getline() );
  103.            Fieldcount = parse( Linebuf, Fields, Fieldsep );
  104.            break;
  105.        case F_STRLEN:         /* calculate length of string argument */
  106.            pushint( strlen( args[0] ) );
  107.            break;
  108.        case F_STRCPY:         /* copy second string argument to first string */
  109.            pushint( strcpy( args[0], args[1] ) );
  110.            break;
  111.        case F_STRCMP:         /* compare two strings */
  112.            pushint( strcmp( args[0], args[1] ) );
  113.            break;
  114.        case F_TOUPPER:       /* convert the character argument to upper case */
  115.            pushint( toupper( args[0] ) );
  116.            break;
  117.        case F_TOLOWER:       /* convert the character argument to lower case */
  118.            pushint( tolower( args[0] ) );
  119.            break;
  120.        case F_MATCH:      /* match a string argument to a regular expression */
  121.            pushint( match( args[0], args[1] ) );
  122.            break;
  123.        case F_NEXTFILE:    /* close current input file and process next file */
  124.            pushint( endfile() );
  125.            break;
  126.        default:           /* oops! */
  127.            error( "bad function call", ACT_ERROR );
  128.         }
  129.     }
  130.  
  131. VARIABLE *
  132. findvar ( s )
  133. char *s;
  134. {     
  135. /*
  136.  * Search the symbol table for a variable whose name is "s".
  137.  */
  138.    VARIABLE *pvar;
  139.     int i;
  140.     char name[ MAXVARLEN ];
  141.  
  142.     i = 0;
  143.     while ( i < MAXVARLEN && alphanum( *s ) ) name[i++] = *s++;
  144.     if ( i<MAXVARLEN ) name[i] = 0;
  145.  
  146.     for ( pvar = Vartab; pvar<Nextvar; ++pvar ) { 
  147.         if ( !strncmp( pvar->vname, name, MAXVARLEN ) ) return pvar;
  148.         }
  149.     return NULL;
  150.     }
  151.  
  152. VARIABLE *
  153. addvar ( name )
  154. char *name;
  155. {     
  156. /*
  157.  * Add a new variable to symbol table and assign it default
  158.  * attributes (int name;)
  159.  */
  160.     int i;
  161.  
  162.     if ( Nextvar <= Vartab + MAXVARTABSZ ) { 
  163.         i = 0;
  164.         while ( i<MAXVARLEN && alphanum( *name ) )
  165.             Nextvar->vname[i++] = *name++;
  166.         if ( i<MAXVARLEN ) Nextvar->vname[i] = 0;
  167.  
  168.         Nextvar->vclass = 0;
  169.         Nextvar->vsize = WORD;
  170.         Nextvar->vlen = 0;
  171. /*
  172.  * Allocate some new room
  173.  */
  174.         Nextvar->vptr = getmem( WORD );
  175.         fillmem( Nextvar->vptr, WORD, 0 );
  176.         }
  177.     else error( "symbol table overflow", MEM_ERROR );
  178.  
  179.     return Nextvar++;
  180.     }
  181.  
  182. declist () {     
  183. /*
  184.  * Parse a "char" or "int" statement.
  185.  */
  186.     char type;
  187.  
  188.     type = Token;
  189.     getoken();
  190.     decl( type );
  191.     while ( Token==T_COMMA ) { 
  192.         getoken();
  193.         decl( type );
  194.         }
  195.     if ( Token==T_SEMICOLON ) getoken();
  196.     }
  197.  
  198. VARIABLE *
  199. decl ( type ) {     
  200. /*
  201.  * Parse an element of a "char" or "int" declaration list.
  202.  * The function stmt_compile() has already entered the variable
  203.  * into the symbol table as an integer, this routine simply changes
  204.  * the symbol's class, size or length according to the declaraction.
  205.  * WARNING: The interpreter depends on the fact that pointers are
  206.  * the same length as int's.  If your machine uses long's for
  207.  * pointers either change the code or #define int long (or whatever).
  208.  */
  209.     char class, size;
  210.     int len;
  211.     unsigned oldsize, newsize;
  212.     VARIABLE *pvar;
  213.  
  214.     if ( Token==T_MUL ) { 
  215. /*
  216.  * it's a pointer
  217.  */
  218.         getoken();
  219.         pvar = decl( type );
  220.         ++pvar->vclass;
  221.         }
  222.     else if ( Token==T_VARIABLE ) { 
  223. /*
  224.  * Simple variable so far.  The token value (in the global
  225.  * "Value" variable) is a pointer to the variable's symbol
  226.  * table entry.
  227.  */
  228.         pvar = (VARIABLE *) Value.dptr;
  229.         getoken();
  230.         class = 0;
  231. /*
  232.  * Compute its length
  233.  */
  234.         if ( Token==T_LBRACKET ) { 
  235. /*
  236.  * It's an array.
  237.  */
  238.             getoken();
  239.             ++class;
  240. /*
  241.  * Compute the dimension
  242.  */
  243.             expression();
  244.             if ( Token!=T_RBRACKET ) error( "missing ']'", ACT_ERROR );
  245.             getoken();
  246.             len = popint();
  247.             }
  248.         else
  249. /*
  250.  * It's a simple variable - array length is zero.
  251.  */
  252.             len = 0;
  253.  
  254.         size = (type==T_CHAR) ? BYTE : WORD;
  255.  
  256.         newsize = (len ? len : 1) * size;
  257.         oldsize = (pvar->vlen ? pvar->vlen : 1) * pvar->vsize;
  258.         if ( newsize != oldsize ) { 
  259. /*
  260.  * The amount of storage needed for the variable
  261.  * has changed - free up memory allocated initially
  262.  * and reallocate for new size.
  263.  */
  264.             free( pvar->vptr );
  265.             pvar->vptr = getmem( newsize );
  266.             }
  267. /*
  268.  * Now change the variable's attributes.
  269.  */
  270.         pvar->vclass = class;
  271.         pvar->vsize = size;
  272.         pvar->vlen = len;
  273.         }
  274.     else syntaxerror();
  275.  
  276.     return pvar;
  277.     }
  278.  
  279. assignment () { 
  280. /*
  281.  * Perform an assignment
  282.  */
  283.     int ival;
  284.  
  285.     ival = popint();
  286. /*
  287.  * make sure we've got an lvalue
  288.  */
  289.     if ( Stackptr->lvalue ) { 
  290.         if ( Stackptr->class ) movemem( &ival, Stackptr->value.dptr, WORD );
  291.         else movemem(&ival, Stackptr->value.dptr, Stackptr->size);
  292.         pop();
  293.         pushint( ival );
  294.         }
  295.     else error( "'=' needs an lvalue", ACT_ERROR );
  296.     }
  297.  
  298. pop () {
  299. /*
  300.  * Pop the stack and return the integer value
  301.  */
  302.     if ( Stackptr >= Stackbtm ) return (Stackptr--)->value.ival;
  303.     return error( "stack underflow", ACT_ERROR );
  304.     }
  305.  
  306. push ( pclass, plvalue, psize, pdatum )
  307. char pclass, plvalue, psize;
  308. DATUM *pdatum;
  309. {     
  310. /*
  311.  * Push item parts onto the stack
  312.  */
  313.     if ( ++Stackptr <= Stacktop ) { 
  314.         Stackptr->lvalue = plvalue;
  315.         Stackptr->size = psize;
  316.         if ( !(Stackptr->class = pclass) && !plvalue )
  317.             Stackptr->value.ival = pdatum->ival;
  318.         else Stackptr->value.dptr = pdatum->dptr;
  319.         }
  320.     else error( "stack overflow", MEM_ERROR );
  321.     }
  322.  
  323. pushint ( intvalue )
  324. int intvalue;
  325. {     
  326. /*
  327.  * push an integer onto the stack
  328.  */
  329.     if ( ++Stackptr <= Stacktop ) { 
  330.         Stackptr->lvalue = Stackptr->class = 0;
  331.         Stackptr->size = WORD;
  332.         Stackptr->value.ival = intvalue;
  333.         }
  334.     else error( "stack overflow", MEM_ERROR );
  335.     }
  336.  
  337. popint () { 
  338. /*
  339.  * Resolve the item on the top of the stack and return it
  340.  */
  341.     int intvalue;
  342.  
  343.     if ( Stackptr->lvalue ) { 
  344. /*
  345.  * if it's a byte indirect, sign extend it
  346.  */
  347.         if ( Stackptr->size == BYTE && !Stackptr->class )
  348.             intvalue = *Stackptr->value.dptr;
  349.         else {     
  350. /*
  351.  * otherwise, it's an unsigned int
  352.  */
  353.             intvalue = (int) *Stackptr->value.ptrptr;
  354.             }
  355.         pop();
  356.         return intvalue;
  357.         }
  358.     else {     
  359. /*
  360.  * else it's an ACTUAL, just pop it
  361.  */
  362.         return pop();
  363.         }
  364.     }
  365.